package cn.touna.jss.modules.third.caridentify;

import cn.touna.risk.api.contraints.facet.First;
import cn.touna.risk.api.contraints.facet.Four;
import cn.touna.risk.api.contraints.facet.Second;
import cn.touna.risk.api.contraints.facet.Three;
import cn.touna.risk.api.enums.SystemErrorCodeEnum;
import cn.touna.jss.common.factory.ResponseFactory;
import cn.touna.jss.common.properties.disconf.CarIdentifyProperties;
import cn.touna.jss.common.util.DateUtils;
import cn.touna.jss.common.util.ValidUtil;
import cn.touna.jss.modules.adapter.ApiMapping;
import cn.touna.jss.modules.custom.cheyiping.dto.MaintenanceRecordRequest;
import cn.touna.jss.modules.custom.cheyiping.utils.CheyipingUtil;
import cn.touna.jss.modules.third.caridentify.entity.CarIdentifyEntity;
import cn.touna.jss.modules.third.caridentify.util.SignUtils;
import cn.touna.risk.api.domain.Response;
import cn.touna.risk.api.http.HttpsUtil;
import cn.touna.risk.cache.redis.RedisCache;
import com.alibaba.fastjson.JSONObject;
import com.touna.loan.log.service.TracerContextUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 车鉴定接口调用
 * Created by 吴柏平 on 2017/8/2.
 */
@Service
public class CarIdentifyService {

    private static final Logger LOGGER = LogManager.getLogger(CarIdentifyService.class);

    @Autowired
    private CarIdentifyProperties carIdentifyProperties;

    @Autowired
    private RedisCache redisCache;

    /**
     * 查询账户信息
     *
     * @return
     * @throws Exception
     */
    @ApiMapping(value="carIdentify.queryAccountInfo",desc="车鉴定.查询账户信息")
    public Response queryAccountInfo() {
        try {
            Map<String, String> bodyMap = new HashMap<String, String>();
            bodyMap.put("uid", carIdentifyProperties.getUid());
            String time = DateUtils.dateTimeToStr(new Date());
            bodyMap.put("time", time); // 时间戳
            bodyMap.put("sign", getSign(time)); // 签名串
            LOGGER.info("查询账户信息请求URL:{}, 请求参数：{}", carIdentifyProperties.getAccountInfoUrl(), bodyMap.toString());
            String result = HttpsUtil.getInstance().post(carIdentifyProperties.getAccountInfoUrl(), getHeaderParam(), bodyMap);
            LOGGER.info("查询账户信息返回结果：{}", result);
            return wrapResponse(result);
        } catch (Exception e) {
            return new Response<>().fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, e.getMessage());
        }
    }

    /**
     * 购买报告2.0版
     *
     * @return
     * @throws Exception
     */
    @ApiMapping(value="carIdentify.buyReport",desc="车鉴定.购买报告2.0版")
    public Response buyReport(CarIdentifyEntity entity) {
        ValidUtil.checkRequestParams(entity, First.class);
        try {
            Map<String, String> bodyMap = new HashMap<String, String>();
            bodyMap.put("uid", carIdentifyProperties.getUid());
            bodyMap.put("vin", entity.getVin());
            bodyMap.put("licensePlate", entity.getLicensePlate());
            bodyMap.put("engine", entity.getEngine());
            bodyMap.put("mobile", entity.getMobile());
            bodyMap.put("orderNo", entity.getOrderNo());
            String time = DateUtils.dateTimeToStr(new Date());
            bodyMap.put("time", time); // 时间戳
            bodyMap.put("sign", getSign(entity.getVin(), time)); // 签名串
            LOGGER.info("购买报告2.0版请求URL:{}, 请求参数：{}", carIdentifyProperties.getBuyUrl(), bodyMap.toString());
            String result = HttpsUtil.getInstance().post(carIdentifyProperties.getBuyUrl(), getHeaderParam(), bodyMap);
            LOGGER.info("购买报告2.0版返回结果：{}", result);
            return wrapResponse(result);
        } catch (Exception e) {
            return new Response<>().fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, e.getMessage());
        }

    }

    /**
     * 查询订单状态
     *
     * @return
     * @throws Exception
     */
    @ApiMapping(value="carIdentify.queryOrderInfo",desc="车鉴定.查询订单状态")
    public Response queryOrderInfo(CarIdentifyEntity entity) {
        ValidUtil.checkRequestParams(entity, Three.class);
        try {
            Map<String, String> bodyMap = new HashMap<String, String>();
            bodyMap.put("uid", carIdentifyProperties.getUid());  //用户ID
            bodyMap.put("orderId", entity.getOrderId());  //接口方返回订单号
            String time = DateUtils.dateTimeToStr(new Date());
            bodyMap.put("time", time); // 时间戳
            bodyMap.put("sign", getSign(entity.getOrderId(), time)); // 签名串
            LOGGER.info("查询订单状态请求URL:{}, 请求参数：{}", carIdentifyProperties.getOrderInfoUrl(), bodyMap.toString());
            String result = HttpsUtil.getInstance().post(carIdentifyProperties.getOrderInfoUrl(), getHeaderParam(), bodyMap);
            LOGGER.info("查询订单状态返回结果：{}", result);
            return wrapResponse(result);
        } catch (Exception e) {
            return new Response<>().fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, e.getMessage());
        }
    }

    /**
     * 查询品牌是否支持
     *
     * @return
     * @throws Exception
     */
    @ApiMapping(value="carIdentify.queryCheckBrand",desc="车鉴定.查询品牌是否支持")
    public Response queryCheckBrand(CarIdentifyEntity entity) {
        ValidUtil.checkRequestParams(entity, Second.class);
        try {
            Map<String, String> bodyMap = new HashMap<String, String>();
            bodyMap.put("uid", carIdentifyProperties.getUid());
            bodyMap.put("vin", entity.getVin());
            String time = DateUtils.dateTimeToStr(new Date());
            bodyMap.put("time", time); // 时间戳
            bodyMap.put("sign", getSign(entity.getVin(), time)); // 签名串
            LOGGER.info("查询品牌是否支持请求URL:{}, 请求参数：{}", carIdentifyProperties.getCheckBrandUrl(), bodyMap.toString());
            String result = HttpsUtil.getInstance().post(carIdentifyProperties.getCheckBrandUrl(), getHeaderParam(), bodyMap);
            LOGGER.info("查询品牌是否支持返回结果：{}", result);
            return wrapResponse(result);
        } catch (Exception e) {
            return new Response<>().fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, e.getMessage());
        }
    }

    /**
     * 通过行驶证图片购买报告
     *
     * @return
     * @throws Exception
     */
    @ApiMapping(value="carIdentify.buyByVinImg",desc="车鉴定.通过行驶证图片购买报告")
    public Response buyByVinImg(CarIdentifyEntity entity) {
        ValidUtil.checkRequestParams(entity, First.class, Four.class);
        try {
            Map<String, String> bodyMap = new HashMap<String, String>();
            bodyMap.put("uid", carIdentifyProperties.getUid());  //用户ID
            bodyMap.put("img_url", entity.getImgUrl());
            bodyMap.put("mobile", entity.getMobile());  //购买人手机号
            bodyMap.put("orderNo", entity.getOrderId());  //第三方订单号
            String time = DateUtils.dateTimeToStr(new Date());
            bodyMap.put("time", time); // 时间戳
            bodyMap.put("sign", getSign(entity.getImgUrl(), time)); // 签名串
            LOGGER.info("通过行驶证图片购买报告请求URL:{}, 请求参数：{}", carIdentifyProperties.getBuyByVinImgUrl(), bodyMap.toString());
            String result = HttpsUtil.getInstance().post(carIdentifyProperties.getBuyByVinImgUrl(), getHeaderParam(), bodyMap);
            LOGGER.info("通过行驶证图片购买报告返回结果：{}", result);
            return wrapResponse(result);
        } catch (Exception e) {
            return new Response<>().fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, e.getMessage());
        }
    }

    /**
     * 查询品牌列表
     *
     * @return
     * @throws Exception
     */
    @ApiMapping(value="carIdentify.queryBrandList",desc="车鉴定.查询品牌列表")
    public Response queryBrandList() {
        try {
            Map<String, String> bodyMap = new HashMap<String, String>();
            bodyMap.put("uid", carIdentifyProperties.getUid());
            String time = DateUtils.dateTimeToStr(new Date());
            bodyMap.put("time", time); // 时间戳
            bodyMap.put("sign", getSign(time)); // 签名串
            LOGGER.info("查询品牌列表请求URL:{}, 请求参数：{}", carIdentifyProperties.getBrandListUrl(), bodyMap.toString());
            String result = HttpsUtil.getInstance().post(carIdentifyProperties.getBrandListUrl(), getHeaderParam(), bodyMap);
            LOGGER.info("查询品牌列表返回结果：{}", result);
            return wrapResponse(result);
        } catch (Exception e) {
            return new Response<>().fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, e.getMessage());
        }
    }


    /**
     * 查询返回report数据
     *
     * @return
     * @throws Exception
     */
    @ApiMapping(value="carIdentify.queryReportData",desc="车鉴定.查询返回report数据")
    public Response queryReportData(CarIdentifyEntity entity) {
        ValidUtil.checkRequestParams(entity, Three.class);
        try {
            Map<String, String> bodyMap = new HashMap<String, String>();
            bodyMap.put("uid", carIdentifyProperties.getUid());
            bodyMap.put("oid", entity.getOrderId());
            String time = DateUtils.dateTimeToStr(new Date());
            bodyMap.put("time", time); // 时间戳
            bodyMap.put("sign", getSign(entity.getOrderId(), time)); // 签名串
            String result = HttpsUtil.getInstance().post(carIdentifyProperties.getReportDataUrl(), getHeaderParam(), bodyMap);

            JSONObject resObj = JSONObject.parseObject(result);
            JSONObject info = resObj.getJSONObject("info");
            String status = info.getString("status");
            if (StringUtils.equals("5", status)) {
                return ResponseFactory.success(result);
            }else {
                return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR,info.getString("message"));
            }
        } catch (Exception e) {
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, e.getMessage());
        }
    }

    private Response getReportImpl(String orderId){
        try {
            Map<String, String> bodyMap = new HashMap<String, String>();
            bodyMap.put("uid", carIdentifyProperties.getUid());
            bodyMap.put("oid", orderId);
            String time = DateUtils.dateTimeToStr(new Date());
            bodyMap.put("time", time); // 时间戳
            bodyMap.put("sign", getSign(orderId, time)); // 签名串
            String result = HttpsUtil.getInstance().post(carIdentifyProperties.getReportDataUrl(), getHeaderParam(), bodyMap);

            JSONObject resObj = JSONObject.parseObject(result);
            JSONObject info = resObj.getJSONObject("info");
            String status = info.getString("status");
            if (StringUtils.equals("5", status)) {
                threadLocal.remove();
                return ResponseFactory.success(resObj);
            }else if(StringUtils.equals("1",status)){
                //请求成功
                Integer i = threadLocal.get();
                if(i == null){
                    i = 1;
                }else{
                    i++;
                }
                if(i < carIdentifyProperties.getReportRetryMaxCount()){
                    threadLocal.set(i);
                    try{
                        TimeUnit.SECONDS.sleep(carIdentifyProperties.getReportRetryIntevalSecond());
                    }catch (Exception e){
                    }
                    return getReportImpl(orderId);
                }
                threadLocal.remove();
                return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR,info.getString("message"));
            } else {
                threadLocal.remove();
                return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR,info.getString("message"));
            }
        } catch (Exception e) {
            threadLocal.remove();
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, e.getMessage());
        }
    }

    private ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
    @ApiMapping(value="carIdentify.getReport",desc="车鉴定.获取报告")
    public Response getReport(MaintenanceRecordRequest request){
        Response response = ValidUtil.valid(request);
        if(response != null)
            return response;
        request.setVin(request.getVin().toUpperCase());

        String key = CheyipingUtil.getRedisKey("carIdentify",request);
        String orderId = null;
        try{
            orderId = redisCache.get(key);
        }catch (Exception e){
            LOGGER.error(e.getMessage(),e);
        }

        if(StringUtils.isEmpty(orderId)){
            CarIdentifyEntity request1 = new CarIdentifyEntity();
            request1.setVin(request.getVin());
            request1.setEngine(request.getEngineNo());
            request1.setMobile(request.getMobile());
            request1.setOrderNo(TracerContextUtil.getTraceId());
            if(request1.getOrderNo() == null){
                request1.setOrderNo(UUID.randomUUID().toString());
            }
            request1.setLicensePlate(request.getPlateNo());
            Response response1 = buyReport(request1);
            if(!response1.checkIfSuccess()){
                return response1;
            }
            JSONObject resObj1 = JSONObject.parseObject((String)response1.getData()).getJSONObject("info");
            String status1 = resObj1.getString("status");
            if("1".equals(status1)){
                orderId = resObj1.getString("orderId");
                redisCache.set(key,orderId,carIdentifyProperties.getOrderIdCacheDays(), TimeUnit.DAYS);
            }else{
                return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR,status1 + ":" + resObj1.getString("message"));
            }
        }
        LOGGER.info("订单号：" + orderId );
        return getReportImpl(orderId);
    }

    private Map<String, String> getHeaderParam() {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("User-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");
        headerMap.put("Connection", "keep-alive");
        headerMap.put("Content-Type", "application/x-www-form-urlencoded");
        return headerMap;
    }

    private String getSign(String... args) {
        StringBuilder data = new StringBuilder();
        data.append(carIdentifyProperties.getUid());
        for (String arg : args) {
            data.append(arg);
        }
        data.append(carIdentifyProperties.getPwd());
        String sign = SignUtils.getSign(data.toString(), carIdentifyProperties.getPrivateKey());
        return sign;
    }

    private Response wrapResponse(String result) {
        LOGGER.info("result : " + result);
        if (StringUtils.isBlank(result)) {
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,"结果为空");
        }
        JSONObject resObj = JSONObject.parseObject(result);
        JSONObject info = resObj.getJSONObject("info");
        String status = info.getString("status");
        if (StringUtils.equals("1", status)) {
            return ResponseFactory.success(result);
        } else {
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR, "buyReport failed,"+status + ":" + info.getString("message") );
        }
    }
}
